package com.gitee.wsl.time.schedule.cron

import com.gitee.wsl.lang.bits.BitSet

enum class CronFieldType(val length: Int, val minAllowedValue: Int, val maxAllowedValue: Int) {
    SECOND(60, 0, 59),
    MINUTE(60, 0, 59),
    HOUR(24, 0, 23),
    DAY(31, 1, 31),
    MONTH(12, 1, 12),
    DAY_OF_WEEK(7, 0, 6);

    val fieldName: String
        get() = name.lowercase()

    fun parseAsterisk(): BitSet {
        if (this == MONTH) {
            return fillBitSet(1, length + 1)
        }
        return fillBitSet(0, length)
    }

    fun parseLastDayOfMonth(): BitSet {
        if (this == DAY) {
            val bitSet: BitSet = fillBitSet(27, length)
            return bitSet
        }
        throw InvalidCronExpressionException("Last day of month is only allowed in day field")
    }

    fun fillBitSetToIncl(from: Int, toIncluded: Int): BitSet {
        var fromIndex = from - minAllowedValue
        var toIndex = toIncluded - minAllowedValue + 1
        if (this == MONTH) {
            fromIndex = from
            toIndex = toIncluded + 1
        }
        return fillBitSet(fromIndex, toIndex)
    }

    fun fillBitSet(from: Int, toExcluded: Int): BitSet {
        val bitSet: BitSet = BitSet(toExcluded)
        bitSet.set(from, toExcluded)
        return bitSet
    }

    fun setBitSet(bitSet: BitSet, number: Int) {
        bitSet.set(if (this == MONTH) number else number - this.minAllowedValue)
    }
}
